package com.tuoyu.peopletest.view.ac;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.stresscube.usbdevice.USBDevicePDHIDWithAddress;
import com.tuoyu.peopletest.R;

import java.util.ArrayList;

public class CalibrationActivity extends NomalBaseActivity implements View.OnClickListener {

    private boolean mbCalibratedBlack=false, mbCalibratedWhite=false, mbCalibratedGray=false;
    TextView mtvMessage;
    ArrayList<Integer> mListResult = new ArrayList<Integer>(); //保存读出来的数据
    int miResult, miResultBlack, miResultWhite, miResultGray;
    int miCalibrate; //0黑 1白 2灰

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public void initContentView() {
        setContentView(R.layout.activity_calibration);

        findViewById(R.id.v_btn_calibration_black).setOnClickListener(this);
        findViewById(R.id.v_btn_calibration_white).setOnClickListener(this);
        findViewById(R.id.v_btn_calibration_gray).setOnClickListener(this);
        mtvMessage=findViewById(R.id.tvMessage);
    }

    @Override
    public void initChildView() {

    }

    @Override
    protected void onStart() {
        super.onStart();
        mDeviceHID.init(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mDeviceHID.release();
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.v_btn_calibration_black:
                if(Calibration(0))
                ((TextView)findViewById(R.id.tvCalibratedBlack)).setText("OK");
                break;
            case R.id.v_btn_calibration_white:
                if(Calibration(1))
                    ((TextView)findViewById(R.id.tvCalibratedWhite)).setText("OK");
                break;
            case R.id.v_btn_calibration_gray:
                if(Calibration(2))
                    ((TextView)findViewById(R.id.tvCalibratedGray)).setText("OK");
                break;
        }
    }

    private boolean bTestRunning=false;
    private boolean Calibration(int color) {
        miCalibrate=color;
        if(bTestRunning) {
            Toast.makeText(this, "正在校准中，请稍后", Toast.LENGTH_SHORT).show();
            return false;
        }
        new Test().start();
        return false;
    }

    void SendDispMessage(String str) {
        Message message = new Message();
        message.what = 1;
        message.obj = str;
        mHandler.sendMessage(message);
    }
    public void DisplayMessage(String msg) {
        mtvMessage.setText(msg + "\r\n" + mtvMessage.getText());
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    DisplayMessage((String) msg.obj);
                    break;
                case 2:
                    switch(msg.arg1) {
                        case 0: ((TextView)findViewById(R.id.tvCalibratedBlack)).setText("OK"); break;
                        case 1: ((TextView)findViewById(R.id.tvCalibratedWhite)).setText("OK"); break;
                        case 2: ((TextView)findViewById(R.id.tvCalibratedGray)).setText("OK"); break;
                    }
                    if(mbCalibratedBlack&&mbCalibratedWhite&&mbCalibratedGray)
                        SaveCalibrateData2Device();
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private void SaveCalibrateData2Device() {
        byte[] head=new byte[8];
        int ver = 0x0102, number = 12;
        int iBuffer=0;
        ConvertInt2Bytes(ver, head, iBuffer);
        iBuffer+=4;
        ConvertInt2Bytes(number, head, iBuffer);
        if(!mDeviceHID.WriteMemoBlock(0, head))
            DisplayMessage("写数据头失败");
        byte[] bytes=new byte[number];
        iBuffer=0;
        ConvertInt2Bytes(miResultBlack, bytes, iBuffer);
        iBuffer+=4;
        ConvertInt2Bytes(miResultWhite, bytes, iBuffer);
        iBuffer+=4;
        ConvertInt2Bytes(miResultGray, bytes, iBuffer);
        if(mDeviceHID.WriteMemoBlock(8, bytes))
            DisplayMessage("保存数据至设备成功");
        else
            DisplayMessage("保存数据至设备失败");
    }

    private void ConvertInt2Bytes(int data, byte[] bytes, int iBuffer) {
        bytes[iBuffer]=(byte)((data&0xFF000000)>>24);
        bytes[iBuffer+1]=(byte)((data&0xFF0000)>>16);
        bytes[iBuffer+2]=(byte)((data&0xFF00)>>8);
        bytes[iBuffer+3]=(byte)(data&0xFF);
    }

    USBDevicePDHIDWithAddress mDeviceHID = new USBDevicePDHIDWithAddress();
    byte ledPosition = (byte) 0x03; //孔位为3
    byte mADPosition = (byte) 0x01; //AD孔位
    int mBrightness=300;
    int mStart = 5;//25;
    int mStop = 100;//125;
    int mWaveLength=2;
    private boolean LEDOn() {
        switch (mWaveLength) {
            case 0:
                return OpenLED365();
            case 1:
                return OpenLED470();
            case 2:
                return OpenLED525_1();
            case 3:
                return OpenLED525_2();
            default:
                return OpenLED470();
        }
    }

    private boolean LEDOff() {
        if (!mDeviceHID.LEDOn(ledPosition, (byte) 0x00, 0)) {
            SendDispMessage("关灯失败");
            return true;
        }
        SendDispMessage("关灯成功");
        return true;
    }
    private boolean OpenLED(byte color) {
        if (!mDeviceHID.LEDOn(ledPosition, color, mBrightness)) {
            SendDispMessage("开灯失败");
            return false;
        }
        SendDispMessage("开灯成功");
        return true;
    }
    private boolean OpenLED365() {
        return OpenLED((byte) 0x15);
    }

    private boolean OpenLED470() {
        return OpenLED((byte) 0x2a);
    }

    private boolean OpenLED525_1() {
        return OpenLED((byte) 0x40);
    }

    private boolean OpenLED525_2() {
        return OpenLED((byte) 0x80);
    }

    class Test extends Thread {
        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            do {
                mDeviceHID.Skip();
//                OpenLED470();
                SendDispMessage("开始测试");
                if (!mDeviceHID.MoveTray(0)) {
                    SendDispMessage("失败，测试退出");
                    break;
                }
                SendDispMessage("开灯");
                if (!LEDOn()) break;
                mListResult.clear();
                SendDispMessage("移动到起点");
                if (!mDeviceHID.MoveTray(mStart)) {
                    SendDispMessage("失败，测试退出");
                    break;
                }
                if (!mDeviceHID.StartADReceive(mADPosition)) break;
                if (mDeviceHID.GetADAfterStart() < 0) break;
                if (mDeviceHID.GetADAfterStart() < 0) break;
                SendDispMessage("开始扫描");
                if (!mDeviceHID.StartMoveTray(mStop)) {
                    SendDispMessage("失败，测试退出");
                    break;
                }
                while (true) { //连续读
                    int data = mDeviceHID.GetADAfterStart();
                    if (data <= 0) {
                        if (!mDeviceHID.StopADReceive()) break;
                        SendDispMessage("结束扫描");
                        break;
                    }
                    mListResult.add(data);
                }
                if (!LEDOff()) break;
                mDeviceHID.MoveTray(0);
                SendDispMessage("结束测试");
                super.run();

                if (mListResult.size() > 10) {
                    int[] datas = new int[mListResult.size()];
                    for (int i = 0; i < mListResult.size(); i++)
                        datas[i] = mListResult.get(i);
                    miResult = GetResult(datas);
                    if(miResult<=0)
                        break;
                    SendDispMessage("测试结果："+miResult);
                    //保存数据
                    SaveData();
                }
            }while(false);
            LEDOff();
            mDeviceHID.MoveTray(0);
            bTestRunning = false;
        }
    }
    void SendCalibrateOK() {
        Message msg=new Message();
        msg.what=2;
        msg.arg1=miCalibrate;
        mHandler.sendMessage(msg);
    }
    private void SaveData() {
        switch(miCalibrate) {
            case 0: miResultBlack=miResult; mbCalibratedBlack=true; break;
            case 1: miResultWhite=miResult; mbCalibratedWhite=true; break;
            case 2: miResultGray=miResult; mbCalibratedGray=true; break;
        }
        SendCalibrateOK();
    }

    //给定数组，排除掉最大值和最小值后，取平均值，如果最大值和最小值在平均值上下20%以内，返回，否则继续
    private int GetResult(int[] r) {
        double upper = 1.2, lower = 0.8;
        while (true) {
            int iMax = -1, iMin = -1, max = -1, min = -1;
            double mean = 0;
            int nData = 0;
            for (int i = 0; i < r.length; i++) {
                if (r[i] == -1)
                    continue;
                mean += r[i];
                nData++;
                if (max == -1 || max < r[i]) {
                    max = r[i];
                    iMax = i;
                }
                if (min == -1 || min > r[i]) {
                    min = r[i];
                    iMin = i;
                }
            }
            mean = mean / nData;
            if (max <= mean * upper && min >= mean * lower)
                return (int) (mean + 0.5);
            if (nData == 0)
                return -1;
            r[iMax]=-1;
            r[iMin]=-1;
        }
    }

}